package com.loe.mvp.ext_app

import android.app.Activity
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.os.Parcelable
import android.util.Log
import android.view.View
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import com.loe.mvp.BaseView
import com.loe.mvp.FragmentPathActivity
import com.loe.mvp.ext_java.delay
import com.loe.mvp.util.LoeRouter
import com.loe.mvp.util.ResultUtil
import com.loe.mvp.util.SUrl
import java.io.Serializable
import java.util.ArrayList
import kotlin.reflect.KClass

fun Context?.openIntent(cls: Class<*>): LoeIntent
{
    if (this == null) return LoeIntent()
    return LoeIntent(this, cls)
}

fun Context?.openIntent(kCls: KClass<*>): LoeIntent
{
    return openIntent(kCls.java)
}

fun Context?.openIntent(url: String): LoeIntent
{
    if (this == null) return LoeIntent()

    if (url.startsWith("http"))
    {
        return LoeIntent(this, url)
    }

    try
    {
        val sUrl = SUrl(url)
        // 未被拦截
        if (LoeRouter.onPageIntercept?.invoke(this, sUrl) != true)
        {
            val intent = openIntent(LoeRouter.getClass(sUrl.path))
            intent.putExtras(sUrl.paramMap)
            if (sUrl.getBoolean("isClearStack"))
            {
                intent.clearTask()
            }
            return intent
        }
    }catch (e: Exception)
    {
        Log.e("runtime", "openIntent: $e")
    }
    return LoeIntent()
}

fun Fragment?.openIntent(cls: Class<*>): LoeIntent
{
    return this?.activity.openIntent(cls)
}

fun Fragment?.openIntent(kCls: KClass<*>): LoeIntent
{
    return this?.activity.openIntent(kCls.java)
}

fun Fragment?.openIntent(url: String): LoeIntent
{
    return this?.activity.openIntent(url)
}

fun View?.openIntent(cls: Class<*>): LoeIntent
{
    return this?.context.openIntent(cls)
}

fun View?.openIntent(kCls: KClass<*>): LoeIntent
{
    return this?.context.openIntent(kCls.java)
}

fun View?.openIntent(url: String): LoeIntent
{
    return this?.context.openIntent(url)
}

class LoeIntent : Intent
{
    companion object
    {
        private var webClass: Class<*>? = null

        fun setWebClass(cls: Class<*>)
        {
            webClass = cls
        }

        fun setWebClass(kCls: KClass<*>)
        {
            webClass = kCls.java
        }
    }

    var context: Context? = null
        private set

    var onResult: ((ResultUtil.ResultBean) -> Unit)? = null
        private set

    var isFrag = false
        private set

    constructor() : super()

    constructor(context: Context) : super()
    {
        this.context = context
    }

    constructor(context: Context, webUrl: String) : super(context, webClass)
    {
        this.context = context
        putExtra("url", webUrl)
    }

    constructor(context: Context?, cls: Class<*>) : super(context, if (Activity::class.java.isAssignableFrom(cls)) cls else FragmentPathActivity::class.java)
    {
        this.context = context

        isFrag = !Activity::class.java.isAssignableFrom(cls)

        if (isFrag)
        {
            putExtra("fragClass", cls.name)
        }
    }

    override fun cloneFilter(): LoeIntent
    {
        super.cloneFilter()
        return this
    }

    override fun setAction(action: String?): LoeIntent
    {
        super.setAction(action)
        return this
    }

    override fun setData(data: Uri?): LoeIntent
    {
        super.setData(data)
        return this
    }

    override fun setDataAndNormalize(data: Uri): LoeIntent
    {
        super.setDataAndNormalize(data)
        return this
    }

    override fun setType(type: String?): LoeIntent
    {
        super.setType(type)
        return this
    }

    override fun setTypeAndNormalize(type: String?): LoeIntent
    {
        super.setTypeAndNormalize(type)
        return this
    }

    override fun setDataAndType(data: Uri?, type: String?): LoeIntent
    {
        super.setDataAndType(data, type)
        return this
    }

    override fun setDataAndTypeAndNormalize(data: Uri, type: String?): LoeIntent
    {
        super.setDataAndTypeAndNormalize(data, type)
        return this
    }

    override fun setIdentifier(identifier: String?): LoeIntent
    {
        super.setIdentifier(identifier)
        return this
    }

    override fun addCategory(category: String?): LoeIntent
    {
        super.addCategory(category)
        return this
    }

    override fun putExtra(name: String?, value: Boolean): LoeIntent
    {
        super.putExtra(name, value)
        return this
    }

    override fun putExtra(name: String?, value: Byte): LoeIntent
    {
        super.putExtra(name, value)
        return this
    }

    override fun putExtra(name: String?, value: Char): LoeIntent
    {
        super.putExtra(name, value)
        return this
    }

    override fun putExtra(name: String?, value: Short): LoeIntent
    {
        super.putExtra(name, value)
        return this
    }

    override fun putExtra(name: String?, value: Int): LoeIntent
    {
        super.putExtra(name, value)
        return this
    }

    override fun putExtra(name: String?, value: Long): LoeIntent
    {
        super.putExtra(name, value)
        return this
    }

    override fun putExtra(name: String?, value: Float): LoeIntent
    {
        super.putExtra(name, value)
        return this
    }

    override fun putExtra(name: String?, value: Double): LoeIntent
    {
        super.putExtra(name, value)
        return this
    }

    override fun putExtra(name: String?, value: String?): LoeIntent
    {
        super.putExtra(name, value)
        return this
    }

    override fun putExtra(name: String?, value: CharSequence?): LoeIntent
    {
        super.putExtra(name, value)
        return this
    }

    override fun putExtra(name: String?, value: Parcelable?): LoeIntent
    {
        super.putExtra(name, value)
        return this
    }

    override fun putExtra(name: String?, value: Array<out Parcelable>?): LoeIntent
    {
        super.putExtra(name, value)
        return this
    }

    override fun putExtra(name: String?, value: Serializable?): LoeIntent
    {
        super.putExtra(name, value)
        return this
    }

    override fun putExtra(name: String?, value: BooleanArray?): LoeIntent
    {
        super.putExtra(name, value)
        return this
    }

    override fun putExtra(name: String?, value: ByteArray?): LoeIntent
    {
        super.putExtra(name, value)
        return this
    }

    override fun putExtra(name: String?, value: ShortArray?): LoeIntent
    {
        super.putExtra(name, value)
        return this
    }

    override fun putExtra(name: String?, value: CharArray?): LoeIntent
    {
        super.putExtra(name, value)
        return this
    }

    override fun putExtra(name: String?, value: IntArray?): LoeIntent
    {
        super.putExtra(name, value)
        return this
    }

    override fun putExtra(name: String?, value: LongArray?): LoeIntent
    {
        super.putExtra(name, value)
        return this
    }

    override fun putExtra(name: String?, value: FloatArray?): LoeIntent
    {
        super.putExtra(name, value)
        return this
    }

    override fun putExtra(name: String?, value: DoubleArray?): LoeIntent
    {
        super.putExtra(name, value)
        return this
    }

    override fun putExtra(name: String?, value: Array<out String>?): LoeIntent
    {
        super.putExtra(name, value)
        return this
    }

    override fun putExtra(name: String?, value: Array<out CharSequence>?): LoeIntent
    {
        super.putExtra(name, value)
        return this
    }

    override fun putExtra(name: String?, value: Bundle?): LoeIntent
    {
        super.putExtra(name, value)
        return this
    }

    override fun putParcelableArrayListExtra(name: String?, value: ArrayList<out Parcelable>?): LoeIntent
    {
        super.putParcelableArrayListExtra(name, value)
        return this
    }

    override fun putIntegerArrayListExtra(name: String?, value: ArrayList<Int>?): LoeIntent
    {
        super.putIntegerArrayListExtra(name, value)
        return this
    }

    override fun putStringArrayListExtra(name: String?, value: ArrayList<String>?): LoeIntent
    {
        super.putStringArrayListExtra(name, value)
        return this
    }

    override fun putCharSequenceArrayListExtra(name: String?, value: ArrayList<CharSequence>?): LoeIntent
    {
        super.putCharSequenceArrayListExtra(name, value)
        return this
    }

    override fun putExtras(src: Intent): LoeIntent
    {
        super.putExtras(src)
        return this
    }

    override fun putExtras(extras: Bundle): LoeIntent
    {
        super.putExtras(extras)
        return this
    }

    override fun replaceExtras(src: Intent): LoeIntent
    {
        super.replaceExtras(src)
        return this
    }

    override fun replaceExtras(extras: Bundle?): LoeIntent
    {
        super.replaceExtras(extras)
        return this
    }

    override fun setFlags(flags: Int): LoeIntent
    {
        super.setFlags(flags)
        return this
    }

    override fun addFlags(flags: Int): LoeIntent
    {
        super.addFlags(flags)
        return this
    }

    override fun setPackage(packageName: String?): LoeIntent
    {
        super.setPackage(packageName)
        return this
    }

    override fun setComponent(component: ComponentName?): LoeIntent
    {
        super.setComponent(component)
        return this
    }

    override fun setClassName(packageContext: Context, className: String): LoeIntent
    {
        super.setClassName(packageContext, className)
        return this
    }

    override fun setClassName(packageName: String, className: String): LoeIntent
    {
        super.setClassName(packageName, className)
        return this
    }

    override fun setClass(packageContext: Context, cls: Class<*>): LoeIntent
    {
        super.setClass(packageContext, cls)
        return this
    }

    fun clearTask(): LoeIntent
    {
        setFlags(FLAG_ACTIVITY_CLEAR_TASK or FLAG_ACTIVITY_NEW_TASK)
        return this
    }

    fun onResult(onResult: (ResultUtil.ResultBean) -> Unit): LoeIntent
    {
        this.onResult = onResult
        return this
    }

    fun onResultOk(onResult: (ResultUtil.ResultBean) -> Unit): LoeIntent
    {
        this.onResult = { if (it.isOk()) onResult(it) }
        return this
    }

    fun start()
    {
        try
        {
            if(context == null) return

            if (onResult == null)
            {
                context?.startActivity(this)
            } else
            {
                if (context is FragmentActivity) ResultUtil.startResult(context as Activity, this, onResult)
            }
        }catch (e: Exception)
        {
            Log.e("runtime", "start: $e")
        }
    }

    fun startFinish(onAfter: (() -> Unit)? = null)
    {
        start()
        if (context is Activity) context.finish()
        onAfter?.invoke()
    }

    fun start(delay: Long, onAfter: (() -> Unit)? = null)
    {
        delay(delay)
        {
            start()
            onAfter?.invoke()
        }
    }

    fun startFinish(delay: Long, onAfter: (() -> Unit)? = null)
    {
        delay(delay)
        {
            start()
            if (context is Activity) context.finish()
            onAfter?.invoke()
        }
    }
}